import { Matrix4 } from "../../core/math/index";
import { mat4 } from "../../core/math/wgpu-matrix.module";
import { Engine } from "../../Engine";

export class GLTFSkin {
  constructor(node, skinObject, name) {
    this.skeleton = skinObject;
    this.parentnode = node;
    this.name = name;
    this.createBoneTexture();
  }

  createBoneTexture() {
    if (!this.skeleton.joints.length) return;
    // 计算满足 256 字节对齐的最小纹理尺寸
    const minSize = Math.max(
      4,
      Math.pow(
        2,
        Math.ceil(
          Math.log(Math.sqrt(this.skeleton.joints.length * 4)) / Math.LN2
        )
      )
    );
    // 确保 bytesPerRow (size * 4 * 4) 是 256 的倍数
    const size = Math.ceil((minSize * 4 * 4) / 256) * (256 / (4 * 4));
    this.boneMatrices = new Float32Array(size * size * 4);
    this.boneTextureSize = size;
    this.boneTexture = Engine.instance.device.createTexture({
      label: "boneTexture",
      size: [size, size],
      format: "rgba32float",
      usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST,
    });
    this.buffer = Engine.instance.device.createBuffer({
      size: this.boneMatrices.byteLength,
      usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST,
    });
  }
  recurve(entity, jointMatrixs) {
    if (entity.components && entity.mesh) {
      const geometry = entity.mesh.geometry;
      geometry.jointMatrixs = jointMatrixs;
    }
    if (entity.children && entity.children.length > 0) {
      for (let index = 0; index < entity.children.length; index++) {
        const eid = entity.children[index];
        let _entity = Engine.instance.register.entityManager.get(eid);
        this.recurve(_entity, jointMatrixs);
      }
    }
  }
  update() {
    if (this.boneTexture) {
      const { inverseBindMatrix, joints } = this.skeleton;
      if (!this.parentnode.id && !this.parentnode.components) {
        return;
      }
      let inverseWorldTransform = this.parentnode.trans.matrixWorld.clone();
      inverseWorldTransform = mat4.create(...inverseWorldTransform.elements);
      const ins = mat4.invert(inverseWorldTransform);
      //   inverseWorldTransform = inverseWorldTransform.invert();
      for (let index = 0; index < joints.length; index++) {
        const node = Engine.instance.register.entityManager.get(joints[index]);
        if (node && node.id && node.components) {
          const nodeWorldMat = node.trans.matrixWorld;
          const data = inverseBindMatrix.slice(index * 16, (index + 1) * 16);
          const ibm = new Matrix4().fromArray(data);
          let jointMatrix = nodeWorldMat.clone();
          const comb = jointMatrix.multiply(ibm);
          const comb1 = mat4.create(...comb.elements);
          const mat = mat4.multiply(ins, comb1);
          //   const mat = inverseWorldTransform.multiply(comb);
          this.boneMatrices.set(mat, index * 16);
        }
      }
      Engine.instance.device.queue.writeBuffer(
        this.buffer,
        0,
        this.boneMatrices
      );
      // 创建命令缓冲区
      const commandEncoder = Engine.instance.device.createCommandEncoder();
      commandEncoder.copyBufferToTexture(
        {
          buffer: this.buffer,
          bytesPerRow: this.boneTextureSize * 4 * 4, // 每行的字节数
          rowsPerImage: this.boneTextureSize, // 每张图片的行数
        },
        {
          texture: this.boneTexture,
          origin: [0, 0],
        },
        [this.boneTextureSize, this.boneTextureSize]
      );
      Engine.instance.device.queue.submit([commandEncoder.finish()]);
      this.recurve(this.parentnode, this.boneTexture);
    }
  }
}
